import SEO from "../components/SEO";
import { TOC, TOCList, TOCLink } from "../components/TOC";
import { Pipe } from "../components/Pipe";
import { Note } from "../components/Note";

<SEO
	title="Slider (range)"
	description="Accessible slider component for React"
/>

# Slider (Range)

<TOC>
	<TOCList>
		<TOCLink href="#slider">Slider</TOCLink>
		<TOCLink href="#sliderinput">SliderInput</TOCLink>
		<TOCLink href="#slidertrack">SliderTrack</TOCLink>
		<TOCLink href="#sliderrange">SliderRange</TOCLink>
		<TOCLink href="#slidermarker">SliderMarker</TOCLink>
		<TOCLink href="#sliderhandle">SliderHandle</TOCLink>
	</TOCList>
</TOC>

- Source: https://github.com/reach/reach-ui/tree/main/packages/slider
- WAI-ARIA: https://www.w3.org/TR/wai-aria-practices-1.2/#slider

A UI input component where the user selects a value from within a given range. A Slider has a handle that can be moved along a track to change its value. When the user's mouse or focus is on the Slider's handle, the value can be incremented with keyboard controls.

Sliders are composed by an outer `Slider` component with a `SliderTrack` child component. `SliderTrack` can accept `SliderRange`, `SliderMarker` and `SliderHandle` components as children.

You can use `Slider` as a simple standalone component, or compose its parts with `SliderInput`.

```jsx
// jsx-demo
function Example() {
	return <Slider />;
}
```

```jsx
// jsx-demo
function Example() {
	return (
		<div>
			<SliderInput>
				<SliderTrack>
					<SliderRange />
					<SliderMarker value={50} />
					<SliderHandle />
				</SliderTrack>
			</SliderInput>
		</div>
	);
}
```

## Installation

From the command line in your project directory, run `npm install @reach/slider` or `yarn add @reach/slider`. Then import the components and styles that you need:

```bash
npm install @reach/slider
# or
yarn add @reach/slider
```

```js
import {
	Slider,
	SliderInput,
	SliderTrack,
	SliderRange,
	SliderHandle,
	SliderMarker,
} from "@reach/slider";
import "@reach/slider/styles.css";
```

## Usage

```jsx
// Basic slider
function Example() {
	return <Slider min={0} max={200} step={10} />;
}

// Composed slider components
function ExampleComposed() {
	return (
		<SliderInput min={0} max={200} step={10}>
			<SliderTrack>
				<SliderRange />
				<SliderHandle />
			</SliderTrack>
		</SliderInput>
	);
}
```

## Slider Events

Prior to v0.10.0, Slider used pointer events for unified event handling across different pointer types (mouse, touch, stylus, etc.). While we still use `onPointerUp` and `onPointerDown` to take advantage of `setPointerCapture` and `releasePointerCapture`, we have moved all other logic to `onMouseDown`, `onTouchStart`, `onMouseUp` and `onTouchEnd` to prevent the need for a polyfill.

Another note on events: because the slider move and end events fire on the document (and because of [some quirks in Chrome related to `onTouchStart`](https://github.com/facebook/react/issues/9809#issuecomment-413978405)), the following event props on `Slider` and `SliderInput` use native DOM events rather than React's synthetic events in their respective handlers.

- `onPointerDown`
- `onPointerUp`
- `onMouseDown`
- `onMouseMove`
- `onMouseUp`
- `onTouchStart`
- `onTouchMove`
- `onTouchEnd`

## Component API

### Slider

High-level component to render a slider in its simplest form. This works simililarly to a native HTML range input.

```jsx
<Slider min={0} max={100} />
```

#### Slider CSS Selectors

Please see the [styling guide](/styling).

```css
[data-reach-slider] {
}
[data-reach-slider][data-disabled] {
}
[data-reach-slider][data-orientation="(horizontal|vertical)"] {
}
```

#### Slider Props

| Prop                                           | Type                                 | Required | Default        |
| ---------------------------------------------- | ------------------------------------ | -------- | -------------- |
| [`children`](#slider-children)                 | `node`                               | true     |                |
| [`defaultValue`](#slider-defaultvalue)         | `number`                             | false    |                |
| [`disabled`](#slider-disabled)                 | `boolean`                            | false    |                |
| [`getAriaLabel`](#slider-getarialabel)         | `func`                               | false    |                |
| [`getAriaValueText`](#slider-getariavaluetext) | `func`                               | false    |                |
| [`handleAlignment`](#slider-handlealignment)   | `"center"` <Pipe /> `"contain"`      | false    | `"center"`     |
| [`max`](#slider-max)                           | `number`                             | false    | `100`          |
| [`min`](#slider-min)                           | `number`                             | false    | `0`            |
| [`name`](#slider-name)                         | `string`                             | false    |                |
| [`onChange`](#slider-onchange)                 | `func`                               | false    |                |
| [`orientation`](#slider-orientation)           | `"horizontal"` <Pipe /> `"vertical"` | false    | `"horizontal"` |
| [`step`](#slider-step)                         | `number`                             | false    | `1`            |
| [`value`](#slider-value)                       | `number`                             | false    |                |

##### Slider `children`

`children?: React.ReactNode`

`Slider` can accept `SliderMarker` children to enhance display of specific values along the track.

```jsx
<Slider min={0} max={100}>
	{new Array(11).fill("x").map((x, index) => (
		<SliderMarker value={index * 10}>
			<span>{index * 10}</span>
		</SliderMarker>
	))}
</Slider>
```

##### Slider `defaultValue`

`defaultValue?: number`

The defaultValue is used to set an initial value for an uncontrolled Slider.

##### Slider `disabled`

`disabled?: boolean`

Whether or not the slider should be disabled from user interaction.

##### Slider `getAriaLabel`

`getAriaLabel?(value: number): string`

A function used to set a human-readable name for the slider.

##### Slider `getAriaValueText`

`getAriaValueText?(value: number): string`

A function used to set a human-readable value text based on the slider's current value.

##### Slider `handleAlignment`

`handleAlignment?: "center" | "contain"`

When set to `center`, the slider's handle will be positioned directly centered over the slider's curremt value on the track. This means that when the slider is at its min or max value, a visiable slider handle will extend beyond the width (or height in vertical mode) of the slider track. When set to `contain`, the slider handle will always be contained within the bounds of the track, meaning its position will be slightly offset from the actual value depending on where it sits on the track.

##### Slider `max`

`max?: number`

The maximum value of the slider. Defaults to `100`.

##### Slider `min`

`min?: number`

The minimum value of the slider. Defaults to `0`.

##### Slider `name`

`name?: string`

If the slider is used as a form input, it should accept a `name` prop to identify its value in context of the form.

##### Slider `onChange`

`onChange?(newValue: number, props?: { min?: number, max?: number, handlePosition?: string }): void`

Callback that fires when the slider value changes. When the `value` prop is set, the Slider state becomes controlled and `onChange` must be used to update the value in response to user interaction.

##### Slider `orientation`

`orientation?: "horizontal" | "vertical"`

Sets the slider to horizontal or vertical mode.

##### Slider `step`

`step?: number`

The step attribute is a number that specifies the granularity that the value must adhere to as it changes. Step sets minimum intervals of change, creating a "snap" effect when the handle is moved along the track.

##### Slider `value`

`value?: number`

An explicit value for the slider. When this prop is used, the Slider state becomes controlled and `onChange` must be used to update the value in response to user interaction.

### SliderInput

The parent component of the slider interface. This is a lower level component if you need more control over styles or rendering the slider's inner components.

#### SliderInput CSS Selectors

See selectors for [`Slider`](#slider-css-selectors).

#### SliderInput Props

`SliderInput` accepts the same props as [`Slider`](#slider-props).

##### SliderInput `children`

`children: React.ReactNode | ((props: { hasFocus?: boolean, id?: string | undefined, sliderId?: string | undefined, max?: number, min?: number, value?: number, valueText?: string | undefined }) => JSX.Element)`

Slider expects `<SliderTrack>` as its child; The track will accept all additional slider sub-components as children. It can also accept a function/render prop as its child to expose some of its internal state variables.

`SliderArgs = { hasFocus: boolean, id: string, max: number, min: number, value: number, valueText: string }`

### SliderTrack

The parent component of the slider's inner components. Represents the visual track on which the slider's handle moves to represent its value.

#### SliderTrack CSS Selectors

Please see the [styling guide](/styling).

```css
[data-reach-slider-track] {
}
[data-reach-slider-track][data-disabled] {
}
[data-reach-slider-track][data-orientation="(horizontal|vertical)"] {
}
```

#### SliderTrack Props

| Prop                                | Type   | Required |
| ----------------------------------- | ------ | -------- |
| [`children`](#slidertrack-children) | `node` | true     |

##### SliderTrack `children`

`children: React.ReactNode`

`SliderTrack` expects `<SliderHandle>`, at minimum, for the Slider to function. All other Slider subcomponents should be passed as children inside the `SliderTrack`.

### SliderRange

The (typically) highlighted portion of the track that represents the space between the slider's `min` value and its current value.

<Note>
	<p>
		<strong>NOTE:</strong> This component was named{" "}
		<code>SliderTrackHighlight</code> in a previous version of Reach UI. That
		component will be dropped in a future version. We recommend updating your
		projects to replace <code>SliderTrackHighlight</code> with{" "}
		<code>SliderRange</code>.
	</p>
</Note>

#### SliderRange CSS Selectors

Please see the [styling guide](/styling).

```css
[data-reach-slider-range] {
}
[data-reach-slider-range][data-disabled] {
}
[data-reach-slider-range][data-orientation="(horizontal|vertical)"] {
}
```

### SliderMarker

A fixed value marker. These can be used to illustrate a range of steps or highlight important points along the slider track.

#### SliderMarker CSS Selectors

Please see the [styling guide](/styling).

```css
[data-reach-slider-marker] {
}
[data-reach-slider-marker][data-disabled] {
}
[data-reach-slider-marker][data-orientation="(horizontal|vertical)"] {
}
[data-reach-slider-marker][data-state="(under|at|over)-value"] {
	/* marker is under, at, or over the slider value */
}
[data-reach-slider-marker][data-value="VALUE_REF"] {
	/* marker is under, at, or over the slider value */
}
```

#### SliderMarker Props

| Prop                           | Type     | Required |
| ------------------------------ | -------- | -------- |
| [`value`](#slidermarker-value) | `number` | true     |

##### SliderMarker `value`

`value: number`

The value to denote where the marker should appear along the track.

### SliderHandle

The handle that the user drags along the track to set the slider value.

#### SliderHandle CSS Selectors

Please see the [styling guide](/styling).

```css
[data-reach-slider-handle] {
}
[data-reach-slider-handle][aria-disabled] {
}
[data-reach-slider-handle][aria-orientation="(horizontal|vertical)"] {
}
```
